package main
import (
  "time"
  "fmt"
  "os"
  "log"
  "io"
  "path"
  "context"
  "os/exec"
  "bufio"
)

const SRT_LOG_PATH = "./srt_log"

type SRT2RTMP struct {
    Streamid string  `json:"streamid"`
    Srt_url   string  `json:"srt_url"`
    Rtmp_url string  `json:"rtmp_url"`
    Start time.Time `json:"start_time"`
    State   string `json:"status"`
    logOutput   *log.Logger
    logFile    *os.File
    //defer srt2rtmp.logFile.Close()
    //DON'T forget close
    ctx context.Context
    cancel context.CancelFunc
}

func (srt2rtmp *SRT2RTMP) Close(){
    srt2rtmp.cancel()
}

func SrtWorker(srt_url string, rtmp_url string, start time.Time, streamid string)(*SRT2RTMP){
    var srt2rtmp SRT2RTMP
    var err error

    srt2rtmp.Streamid = streamid
    srt2rtmp.Srt_url = srt_url
    srt2rtmp.Rtmp_url = rtmp_url 
    if start.IsZero() {
        srt2rtmp.Start = time.Now()
    }else {
        srt2rtmp.Start = start
    }
    srt2rtmp.State = "inited"

    logfile := path.Join(SRT_LOG_PATH, streamid)
    if _, err := os.Stat(SRT_LOG_PATH); os.IsNotExist(err) {
        os.Mkdir(SRT_LOG_PATH, os.ModePerm)
    }
    srt2rtmp.logFile, err  = os.OpenFile(logfile, os.O_CREATE | os.O_WRONLY | os.O_APPEND, 0666)
    if err != nil {
        log.Fatalln("open file error !")
    }
    srt2rtmp.logOutput = log.New(srt2rtmp.logFile, "", log.Lshortfile | log.Ltime)
    srt2rtmp.logOutput.Println("Srt:", srt_url, "Started")

    srt2rtmp.ctx, srt2rtmp.cancel = context.WithCancel(context.Background())
    fmt.Printf("%+v\n", srt2rtmp)
    go doSrtStuff(&srt2rtmp)
    return &srt2rtmp
}

func doSrtStuff(srt2rtmp * SRT2RTMP) {
    srt2rtmp.State = "running"
    cmd := exec.CommandContext(srt2rtmp.ctx, "./srt2rtmp", srt2rtmp.Srt_url, srt2rtmp.Rtmp_url)
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
    }
    defer stdout.Close()

    if err := cmd.Start(); err != nil{
        fmt.Println(err)
    }
    input := make(chan int, 1)
    go func (input chan int, stdout io.Reader){
        br := bufio.NewReaderSize(stdout, 128)
        for {
            w, _, err := br.ReadLine()
            if err != nil {
                 break
            }
            if len(w) > 0 {
                input <- 1
                srt2rtmp.logOutput.Println(string(w))
            }
        }
    }(input, stdout)

LOOP:
    for {
        select {
            //timeout
            case <- srt2rtmp.ctx.Done(): {
                break LOOP
            }
            default:
        }
        select {
            case <-input:
            case <-time.After(10 * time.Second):
                srt2rtmp.State = "nodata"
                fmt.Println("timed out")
        }
    }

    cmd.Wait()
    srt2rtmp.logOutput.Println("Srt: ", srt2rtmp.Srt_url, "Exited")
    srt2rtmp.logFile.Close()
}

func tmain(){

     r := SrtWorker("srt://localhost:8080?streamid=live.17zuoye.cn/live/test", "rtmp://localhost/live/test", time.Now(), "333")
     fmt.Println(r)
     for {
         time.Sleep(1 * time.Second)
        // r.cancel()
     }
}
